﻿using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using System.Runtime.InteropServices;
using System.Windows.Forms;

using JsGame;
using JsEditor;
using System.Text;



namespace JsEditor
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class MainGame : WinFormGame
    {

        public enum GameMode
        {
            SceneEventEdit,
            SceneEdit,
            PicChoose,
            HeadChoose,
        }

        Texture2D pic_selected;
        Texture2D box, pic_in, pic_out, pic_sub_in, pic_sub_out;
        SpriteFont font;

        public GameMode Mode = GameMode.SceneEventEdit;


        #region MonoGame主要函数



        public override void OnResize(Object sender, EventArgs e)
        {
            base.OnResize(sender, e);
            //重新计算网格
            if (Mode == GameMode.PicChoose)
                ResetCell();
        }

        public override void Init()
        {
            Content.RootDirectory = "Content";
            pic_selected = Content.Load<Texture2D>("selected");
            box = Content.Load<Texture2D>("box");
            pic_in = Content.Load<Texture2D>("in");
            pic_out = Content.Load<Texture2D>("out");
            pic_sub_in = Content.Load<Texture2D>("sub_in");
            pic_sub_out = Content.Load<Texture2D>("sub_out");
            font = Content.Load<SpriteFont>("font12");
        }

        public override void Deinit()
        {
            // Content.Unload();
        }

        public override void Update(int dtime)
        {

        }


        public override void Draw()
        {
            if (Mode == GameMode.SceneEventEdit || Mode == GameMode.SceneEdit)
            {
                if (CurrentScene != null)
                    DrawScene();
            }
            else if (Mode == GameMode.PicChoose)
            {
                DrawPicList();
            }
        }
        #endregion
        //========================================================================
        #region 公有变量
        public bool[] LevelVisible = new bool[5] { true, true, true, true, true };
        public Vector2 MapOffset = Vector2.Zero, LastMapOffset;
        public int SelectX, SelectY, SelectIndex;
        public int CellX, CellY, CellW, CellH;
        public int CellOffsetY;
        public int CurrentLevel = -1;
        public int CurPaintPicIdx, CurPaintPicOffset;

        public JsScene CurrentScene, LastScene;
        public List<JsScene> SceneList = new List<JsScene>();
        public List<string> TalkList = new List<string>();
        public List<JsPic> PicList = new List<JsPic>();
        public List<JsEvent> EventList = new List<JsEvent>();
        public List<JsSkill> SkillList = new List<JsSkill>();
        public List<JsItem> ItemList = new List<JsItem>();
        public List<JsNPC> NPCList = new List<JsNPC>();
        
        public List<int> ItemTypeList = new List<int>();
        public List<int> ItemCountList = new List<int>();
        public List<JsShop> ShopList = new List<JsShop>();
        public List<JsSuit> SuitList = new List<JsSuit>();
        public List<ushort> TeamNPCList = new List<ushort>();
        public List<ushort> TaskList = new List<ushort>();
        public List<ushort> CurTaskList = new List<ushort>();
        public RGRP rgrp = new RGRP();
        public JsTeam Team = new JsTeam();

        #endregion

        #region Form响应函数


        public void MouseWheel(int d)
        {
            if (d > 0)
            {
                CellScrollY((Height / CellH) * CellH);
            }
            else if (d < 0)
            {
                CellScrollY((Height / CellH) * -CellH);
            }
        }

        public void MouseRightDrag(int dx, int dy)
        {
            if (Mode == GameMode.PicChoose)
            {
                CellScrollY(dy);
            }
            else //if (Mode == GameMode.SceneEventEdit)
            {
                if (CurrentScene != null)
                {
                    MapOffset.X -= dx;
                    MapOffset.Y -= dy;
                }
            }
        }

        public void MouseMove(int x, int y)
        {
            if (Mode == GameMode.PicChoose)
            {
                SelectY = (y + CellOffsetY) / CellH;
                SelectX = x / CellW;
            }
            else //if (Mode == GameMode.SceneEventEdit)
            {
                if (CurrentScene != null)
                {
                    x += (int)MapOffset.X;
                    y += (int)MapOffset.Y + 18;
                    SelectX = ((y * 2 + x) / 36);
                    SelectY = ((y * 2 - x) / 36);
                }
            }
        }


        #endregion
        
        public JsPic CreatePic(byte[] buffer, Color[] pal)
        {
            JsPic pic = new JsPic();
            short w = BitConverter.ToInt16(buffer, 0);
            short h = BitConverter.ToInt16(buffer, 2);
            pic.size.X = w;
            pic.size.Y = h;
            pic.offset.X = BitConverter.ToInt16(buffer, 4);
            pic.offset.Y = BitConverter.ToInt16(buffer, 6);
            pic.texture = new Texture2D(this.GraphicsDevice, w, h, false, SurfaceFormat.Color);
            Color[] data = new Color[w * h];
            for (int i = 0; i < data.Length; i++)
                data[i] = Color.Transparent;

            int start = 8;
            int y = 0;
            while (start < buffer.Length && y < h)
            {
                int x = 0;
                int line_len = buffer[start]; start++;
                int line_end = start + line_len;
                while (start < line_end)
                {
                    int len = buffer[start]; start++;  //透明个数
                    x += len;
                    len = buffer[start]; start++;  //不透明个数
                    for (int i = 0; i < len; i++)
                        data[y * w + x++] = pal[buffer[start++]];
                }
                y++;
            }
            pic.texture.SetData<Color>(data);
            data = null;
            return pic;
        }

        public void LoadPic()
        {
            //读取调色板
            Color[] pal = new Color[256];
            byte[] buf = new byte[4];
            FileStream fs = File.OpenRead("resource\\td\\resource\\mmap.col");
            for (int i = 0; i < pal.Length; i++)
            {
                fs.Read(buf, 0, 3);
                pal[i].R = (byte)(buf[0] * 4);
                pal[i].G = (byte)(buf[1] * 4);
                pal[i].B = (byte)(buf[2] * 4);
                pal[i].A = 0xff;
            }
            fs.Close();
            //读取图片索引            
            fs = File.OpenRead("resource\\td\\resource\\sdx");
            int count = (int)(fs.Seek(0, SeekOrigin.End) / 4);
            int[] offset = new int[count];
            fs.Seek(0, SeekOrigin.Begin);
            BinaryReader br = new BinaryReader(fs);
            for (int i = 0; i < count; i++)
                offset[i] = br.ReadInt32();
            br.Close();
            fs.Close();
            //读取图片数据
            fs = File.OpenRead("resource\\td\\resource\\smp");
            int start = 0;
            for (int i = 0; i < count; i++)
            {
                int size = offset[i] - start;
                if (size > 0)
                {
                    buf = new byte[size];
                    fs.Read(buf, 0, size);

                    //创建图片
                    JsPic pic = CreatePic(buf, pal);
                    if (pic != null)
                    {
                        pic.idx = (ushort)i;
                    }
                    PicList.Add(pic);
                }
                else
                    PicList.Add(null);

                start = offset[i];
            }
            fs.Close();
        }

        public string LoadTalk()
        { 
            try
            {
                //读取对话索引   
                var fs = File.OpenRead("resource\\td\\resource\\talk.idx");
                int count = (int)(fs.Seek(0, SeekOrigin.End) / 4);
                int[] offset = new int[count];
                fs.Seek(0, SeekOrigin.Begin);
                BinaryReader br = new BinaryReader(fs);
                for (int i = 0; i < count; i++)
                    offset[i] = br.ReadInt32();
                br.Close();
                fs.Close();

                //读取对话数据
                fs = File.OpenRead("resource\\td\\resource\\talk.grp");
                int start = 0;
                var encoding = System.Text.Encoding.GetEncoding("GBK");
                for (int i = 0; i < count; i++)
                {
                    int size = offset[i] - start -1;  //去掉最后一个字节0
                    if (size > 0)
                    {
                        byte[] line = new byte[size];
                        fs.Read(line, 0, size);
                        for (int j = 0; j < size; j++)
                            line[j] = (byte)~line[j];
                        TalkList.Add(encoding.GetString(line));
                        fs.ReadByte();
                    }
                    else
                        TalkList.Add("");
                    start = offset[i];
                }
                fs.Close();
                if (!File.Exists("resource\\talk.txt"))
                    SaveTalkToTxt("resource\\talk.txt");
                return null;
            }
            catch(Exception e)
            {
                return e.ToString();
            }
        }

        public string SaveTalk()
        {
            try
            {
                //保存对话索引   
                var fs = File.OpenWrite("resource\\td\\resource\\talk.idx");
                var fg = File.OpenWrite("resource\\td\\resource\\talk.grp");
                int len = 0;
                var encoding = System.Text.Encoding.GetEncoding("GBK");
                byte[] buf=new byte[4];
                for(int i=0;i<TalkList.Count;i++)
                {
                    byte[] bytes=encoding.GetBytes(TalkList[i]);
                    len += bytes.Length + 1;
                    fs.WriteByte((byte)( len &  0xff));
                    fs.WriteByte((byte)((len & 0xff00)>>8));
                    fs.WriteByte((byte)((len & 0xff0000) >>16));
                    fs.WriteByte((byte)((len & 0xff000000) >> 24));
                    for(int j=0;j<bytes.Length;j++)
                        bytes[j]=(byte)~bytes[j];
                    fg.Write(bytes, 0, bytes.Length);
                    fg.WriteByte(0);
                }
                fs.Close();
                fg.Close();
                return null;
            }
            catch (Exception e)
            {
                return e.ToString();
            }

        }

        public string LoadTeamNPC()
        {
            try
            {
                TeamNPCList.Clear();
                var fs = File.OpenRead("resource\\lists\\list\\leave.bin");
                var br = new BinaryReader(fs);
                try
                {
                    ushort v = br.ReadUInt16();
                    while (v != 0)
                    {
                        TeamNPCList.Add(v);
                        v = br.ReadUInt16();
                    }
                }
                catch(EndOfStreamException e)
                {
                    //
                }
                br.Close();
                fs.Close();
                return null;
            }
            catch (Exception e)
            {
                return e.ToString();
            }
        }

        /* 
         * match.bin（3546 bytes）是武器和武功的配合 3个short ，第一个是武器id，第二个是武功id，第三个是附加的威力（实际威力要把这个数值乘2）
         * match1.bin（3546 bytes）是轻功和武功的配合，同上
         * match2.bin（6818 bytes）是内功和武功的配合，同上
         * levelup.bin（202 bytes）是各个等级所需要的经验值
         * leave.bin（402 bytes）是可以离队的人员编号（short）
         * Comprehend.bin(1600 bytes) 是组合大决，第三个short是分别是武功id，最后一个short是形成的组合武功id
        */

        public string LoadSuit()
        {
            try
            {
                var fs = File.OpenRead("resource\\lists\\list\\suit.bin");
                int count = (int)(fs.Seek(0, SeekOrigin.End) / 48);
                fs.Seek(0, SeekOrigin.Begin);
                BinaryReader br = new BinaryReader(fs);
                for (int i = 0; i < count; i++)
                {
                    JsSuit s = new JsSuit();
                    s.idx = i;
                    s.Read(br);
                    SuitList.Add(s);
                }
                br.Close();
                fs.Close();
                return null;
            }
            catch (Exception e)
            {
                return e.ToString();
            }
        }

        public string SaveSuit()
        {
            try
            {
                var fs = File.OpenWrite("resource\\lists\\list\\suit.bin");
                fs.Seek(0, SeekOrigin.Begin);
                BinaryWriter bw = new BinaryWriter(fs);
                foreach(var s in SuitList)
                    s.Save(bw);
                bw.Close();
                fs.Close();
                return null;
            }
            catch (Exception e)
            {
                return e.ToString();
            }
        }

        public string LoadEvent()
        {
            try
            {
                EventList.Clear();
                TaskList.Clear();

                byte[] buf;
                //读取索引            
                FileStream fs = File.OpenRead("resource\\td\\resource\\kdef.idx");
                int count = (int)(fs.Seek(0, SeekOrigin.End) / 4);
                int[] offset = new int[count];
                fs.Seek(0, SeekOrigin.Begin);
                BinaryReader br = new BinaryReader(fs);
                for (int i = 0; i < count; i++)
                    offset[i] = br.ReadInt32();
                br.Close();
                fs.Close();
                
                //读取数据
                fs = File.OpenRead("resource\\td\\resource\\kdef.grp");
                int start = 0;
                for (int i = 0; i < count; i++)
                {
                    int size = offset[i] - start;
                    if (size > 0)
                    {
                        JsEvent e = new JsEvent();
                        e.idx = i;
                        buf = new byte[size];
                        fs.Read(buf, 0, size);
                        int p = 0;
                        //创建事件
                        while (p < size)
                        {
                            ushort cmd=BitConverter.ToUInt16(buf, p); p+=2;
                            JsEventType type = JsEventType.GetEventType(cmd);
                            if (type == null) 
                                type = new JsEventType(cmd, (ushort)((size - p) / 2),"未知" + cmd.ToString());
                            JsEventLine el=new JsEventLine(type);
                            el.idx = e.Lines.Count;
                            for (int j = 0; j < type.len; j++)
                            {
                                el.values[j] = BitConverter.ToUInt16(buf, p);
                                p += 2;
                            }
                            e.Lines.Add(el);
                            if(type.cmd == 77 || type.cmd == 78) //增加或完成任务
                            {
                                if (!TaskList.Contains(el.values[0]))
                                    TaskList.Add(el.values[0]);
                            }
                        }
                        EventList.Add(e);
                    }
                    else
                        EventList.Add(null);
                    start = offset[i];
                }

                fs.Close();
                if (!File.Exists("resource\\kdef.txt"))
                    SaveEventToTxt("resource\\kdef.txt");
                return null;
            }
            catch(Exception e)
            {
                return e.ToString();
            }
        }

        public void SaveEventToTxt(string filename)
        {
            var fs = File.OpenWrite(filename);
            StreamWriter sw = new StreamWriter(fs);
            foreach (var e in EventList)
            {
                foreach (var el in e.Lines)
                {
                    sw.Write("[");
                    sw.Write(el.type.cmd.ToString());
                    sw.Write("]");
                    for (int i = 0; i < el.values.Length; i++)
                    {
                        if (i > 0) sw.Write(",");
                        sw.Write(el.values[i]);
                    }
                }
                sw.WriteLine();
            }
            sw.Close();
            fs.Close();
        }

        public void SaveTalkToTxt(string filename)
        {
            var fs = File.OpenWrite(filename);
            StreamWriter sw = new StreamWriter(fs);
            foreach (var e in TalkList)
            {
                sw.WriteLine(e);
            }
            sw.Close();
            fs.Close();
        }

        public string SaveEvent()
        {
            try
            {
                var fs = File.OpenWrite("resource\\td\\resource\\kdef.idx");
                var fg = File.OpenWrite("resource\\td\\resource\\kdef.grp");
                int len = 0;
                byte[] buf = new byte[4];
                foreach(var e in EventList)
                {
                    foreach(var el in e.Lines)
                    {
                        fg.WriteByte((byte)(el.type.cmd & 0xff));
                        fg.WriteByte((byte)(el.type.cmd >> 8));
                        for (int i = 0; i < el.values.Length; i++)
                        {
                            fg.WriteByte((byte)(el.values[i] & 0xff));
                            fg.WriteByte((byte)(el.values[i] >>8));
                        }
                        len += el.values.Length * 2+2;
                    }
                    fs.WriteByte((byte)(len & 0xff));
                    fs.WriteByte((byte)((len & 0xff00) >> 8));
                    fs.WriteByte((byte)((len & 0xff0000) >> 16));
                    fs.WriteByte((byte)((len & 0xff000000) >> 24));
                }
                fs.Close();
                fg.Close();
                return null;
            }
            catch (Exception e)
            {
                return e.ToString();
            }

        }

        public void DrawPicList()
        {
            spriteBatch.Begin();
            Rectangle rect;
            rect.Y = -CellOffsetY;
            rect.Width = CellW;
            rect.Height = CellH;
            Vector2 pos = Vector2.Zero;
            for (int i = 0; i < PicList.Count; i += CellX)
            {
                for (int j = 0; j < CellX; j++)
                {
                    int idx = i + j;
                    if (idx < PicList.Count)
                    {
                        rect.X = j * CellW;
                        if (rect.Y + CellH >= 0f && rect.Y < Height)
                        {
                            if (SelectX >= 0 && SelectX < CellX && SelectX + SelectY * CellX == idx)
                                spriteBatch.Draw(box, rect, Color.Red);
                            else if (idx == SelectIndex)
                            {
                                spriteBatch.Draw(box, rect, Color.White);
                            }
                            JsPic pic = PicList[idx];
                            if (pic != null && pic.texture != null)
                            {
                                DrawPicCenterScale(pic.texture, rect);
                            }
                            string str = (idx * 2).ToString();
                            pos.X = rect.X;
                            pos.Y = rect.Y;
                            spriteBatch.DrawString(font, str, pos, Color.Black);
                            pos.X += 1f;
                            pos.Y += 1f;
                            spriteBatch.DrawString(font, str, pos, Color.White);

                        }
                    }
                }
                rect.Y += CellH;
            }
            spriteBatch.End();
        }

        public void DrawPicCenterScale(Texture2D texture, Rectangle rect)
        {
            Rectangle r = rect;
            if (rect.Width * texture.Height >= rect.Height * texture.Width)  //空间横长
            {
                r.Width = rect.Height * texture.Width / texture.Height;
                r.Height = rect.Height;
                r.X = rect.X + (rect.Width - r.Width) / 2;
                r.Y = rect.Y;
            }
            else  //竖长
            {
                r.Height = rect.Width * texture.Height / texture.Width;
                r.Width = rect.Width;
                r.Y = rect.Y + (rect.Height - r.Height);
                r.X = rect.X; ;
            }
            spriteBatch.Draw(texture, r, Color.White);

        }


        public void DrawScene()
        {
            Vector2 pos;
            spriteBatch.Begin();

            for (int l = 0; l < 3; l++)
                if (LevelVisible[l])
                    for (int y = 0; y < 64; y++)
                        for (int x = 0; x < 64; x++)
                        {
                            int idx;
                            if (CurrentLevel == l && SelectX == x && SelectY == y)
                            {
                                idx = CurPaintPicIdx;
                            }
                            else
                            {
                                idx = CurrentScene.map[l, y, x] / 2;
                            }
                            if (idx > 0 && idx < PicList.Count)
                            {
                                JsPic pic = PicList[idx];
                                if (pic != null && pic.texture != null)
                                {
                                    pos.X = (x - y) * 18;
                                    pos.Y = (x + y) * 9;
                                    if (l > 0)
                                        pos.Y -= (short)CurrentScene.map[l + 3, y, x];
                                    pos -= pic.offset + MapOffset;
                                    spriteBatch.Draw(pic.texture, pos, Color.White);
                                }
                            }
                        }
            //事件层
            if (LevelVisible[3])
            {
                for (int y = 0; y < 64; y++)
                    for (int x = 0; x < 64; x++)
                    {
                        int idx = CurrentScene.map[3, y, x];
                        if (idx >= 0 && idx < 200)
                        {
                            JsSceneEvent e = CurrentScene.events[idx];
                            if (!e.IsNull())
                            {
                                JsPic pic;
                                pos.X = (x - y) * 18;
                                pos.Y = (x + y) * 9;
                                pos.Y -= (short)CurrentScene.map[4, y, x];
                                pos -= MapOffset;

                                //事件中的图片
                                int pic_idx = e.values[5] / 2;
                                if (pic_idx > 0 && pic_idx < PicList.Count)
                                {
                                    pic = PicList[pic_idx];
                                    if (pic != null && pic.texture != null)
                                        spriteBatch.Draw(pic.texture, pos - pic.offset, Color.White);
                                }
                                pic = PicList[1];
                                if (pic != null && pic.texture != null)
                                {
                                    spriteBatch.Draw(pic.texture, pos - pic.offset, Color.White);
                                }


                                //显示场景事件编码
                                if (LevelVisible[4])
                                {
                                    pos.X -= 9;
                                    pos.Y -= 18;
                                    spriteBatch.DrawString(font, idx.ToString(), pos, Color.Black);
                                    pos.X -= 2;
                                    pos.Y -= 2;
                                    spriteBatch.DrawString(font, idx.ToString(), pos, Color.White);
                                }

                            }
                        }
                    }
            }

            //场景入口
            Point p = CurrentScene.GetEnter();
            if (p != Point.Zero)
            {
                pos.X = (p.X - p.Y) * 18 - 18;
                pos.Y = (p.X + p.Y) * 9 - 18;
                pos -= MapOffset;
                spriteBatch.Draw(pic_in, pos, Color.White);
            }
            //场景出口0-3
            p = CurrentScene.GetExit(0);
            if (p != Point.Zero)
            {
                pos.X = (p.X - p.Y) * 18 - 18;
                pos.Y = (p.X + p.Y) * 9 - 18;
                pos -= MapOffset;
                spriteBatch.Draw(pic_out, pos, Color.White);
            }
            p = CurrentScene.GetExit(1);
            if (p != Point.Zero)
            {
                pos.X = (p.X - p.Y) * 18 - 18;
                pos.Y = (p.X + p.Y) * 9 - 18;
                pos -= MapOffset;
                spriteBatch.Draw(pic_out, pos, Color.White);
            }
            p = CurrentScene.GetExit(2);
            if (p != Point.Zero)
            {
                pos.X = (p.X - p.Y) * 18 - 18;
                pos.Y = (p.X + p.Y) * 9 - 18;
                pos -= MapOffset;
                spriteBatch.Draw(pic_out, pos, Color.White);
            }
            if (CurrentScene.GetSubSceneIdx() < SceneList.Count)
            {
                //子场景入口
                p = CurrentScene.GetSubEnter();
                pos.X = (p.X - p.Y) * 18 - 18;
                pos.Y = (p.X + p.Y) * 9 - 18;
                pos -= MapOffset;
                spriteBatch.Draw(pic_sub_in, pos, Color.White);
                //子场景出口
                p = CurrentScene.GetSubExit();
                pos.X = (p.X - p.Y) * 18 - 18;
                pos.Y = (p.X + p.Y) * 9 - 18;
                pos -= MapOffset;
                spriteBatch.Draw(pic_sub_out, pos, Color.White);
            }

            //当前选择
            if (SelectX >= 0 && SelectX < 64 && SelectY >= 0 && SelectY < 64)
            {
                JsPic pic = PicList[1];
                pos.X = (SelectX - SelectY) * 18 - 18;
                pos.Y = (SelectX + SelectY) * 9 - 18;
                pos -= MapOffset;
                spriteBatch.Draw(pic_selected, pos, Color.White);
                int y = (short)CurrentScene.map[4, SelectY, SelectX];
                if (y != 0)
                {
                    pos.Y -= y;
                    spriteBatch.Draw(pic_selected, pos, Color.Red);
                }
            }
            //地图坐标
            pos.X = 2f; pos.Y = 2f;
            string pos_str = string.Format("{0:00},{1:00}", SelectX, SelectY);
            spriteBatch.DrawString(font, pos_str, pos, Color.Black);
            pos.X -= 2f; pos.Y -= 2f;
            spriteBatch.DrawString(font, pos_str, pos, Color.White);

            spriteBatch.End();
        }

        
         public string LoadRGRP(string path)
        {
            try
            {
                var fs = File.OpenRead(path+"\\save\\r.grp");
                var br = new BinaryReader(fs);

                rgrp.h1 = br.ReadUInt16();
                rgrp.in_scene = br.ReadUInt16();
                rgrp.bigmap_x = br.ReadUInt16();
                rgrp.bigmap_y = br.ReadUInt16();
                rgrp.scene_x = br.ReadUInt16();
                rgrp.scene_y = br.ReadUInt16();
                br.Read(rgrp.unknow0, 0, rgrp.unknow0.Length);
                rgrp.scene_id = br.ReadInt16();
                br.Read(rgrp.unknow1, 0, rgrp.unknow1.Length);
                br.Read(rgrp.nogninnur, 0, rgrp.nogninnur.Length);
                br.Read(rgrp.version, 0, rgrp.version.Length);

                ItemTypeList.Clear();
                ItemCountList.Clear();
                int count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                    ItemTypeList.Add(br.ReadInt32());
                count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                    ItemCountList.Add(br.ReadInt32());
                //读取npc
                NPCList.Clear();
                count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                {
                    JsNPC npc = new JsNPC();
                    NPCList.Add(npc);
                    npc.idx = (ushort)i;
                    npc.Read(br);
                }
                //读取item
                ItemList.Clear();
                count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                {
                    JsItem item = new JsItem();
                    ItemList.Add(item);
                    item.idx = (ushort)i;
                    item.Read(br);
                }
                //读取scene
                SceneList.Clear();
                count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                {
                    JsScene scene = new JsScene();
                    SceneList.Add(scene);
                    scene.idx = (ushort)i;
                    scene.Read(br);
                }
                //读取skill
                SkillList.Clear();
                count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                {
                    JsSkill skill = new JsSkill();
                    SkillList.Add(skill);
                    skill.idx = (ushort)i;
                    skill.Read(br);
                }
                //读取Shop
                ShopList.Clear();
                count = br.ReadInt32();
                for (int i = 0; i < count; i++)
                {
                    JsShop shop = new JsShop();
                    ShopList.Add(shop);
                    shop.idx = (ushort)i;
                    shop.Read(br);
                }
                //读取队友
                for (int i = 0; i < Team.values.Length; i++)
                    Team.values[i] = (ushort)br.ReadInt32();
                //收尾
                br.Read(rgrp.md5, 0, rgrp.md5.Length);
                rgrp.week=br.ReadInt32();
                rgrp.diffculty = br.ReadInt32();
                rgrp.game_mode = br.ReadInt32();
                br.Read(rgrp.charmap, 0, rgrp.charmap.Length); //256
                rgrp.game_time = br.ReadUInt32();
                rgrp.total_game_time = br.ReadUInt32();
                rgrp.save_time = br.ReadUInt32();
                rgrp.unknow_int = br.ReadInt32();
                fs.Read(rgrp.ender, 0, rgrp.ender.Length);  //1072
                br.Close();
                fs.Close();
                //读取scene map
                fs = File.OpenRead(path + "\\save\\s.grp");
                br = new BinaryReader(fs);
                //count = (int)(fs.Seek(0, SeekOrigin.End) / 49152);
                fs.Seek(0, SeekOrigin.Begin);
                for (int i = 0; i < SceneList.Count; i++)
                {
                    for (int level = 0; level < 6; level++)
                        for (int y = 0; y < 64; y++)
                            for (int x = 0; x < 64; x++)
                                SceneList[i].map[level, y, x] = br.ReadUInt16();
                }
                br.Close();
                fs.Close();
                //读取scene event
                fs = File.OpenRead(path+"\\save\\d.grp");
                br = new BinaryReader(fs);
                fs.Seek(0, SeekOrigin.Begin);
                for (int i = 0; i < SceneList.Count; i++)
                    for (int j = 0; j < 200; j++)
                    {
                        JsSceneEvent e = SceneList[i].events[j] = new JsSceneEvent();
                        e.idx = j;
                        e.Read(br);

                    }
                br.Close();
                fs.Close();
                return null;
            }
            catch(Exception e)
            {
                return e.ToString();
            }
        }

        public string SaveRGRP(string path)
        {
            try
            {
                var fs = File.OpenWrite(path+"\\save\\r.grp");
                BinaryWriter bw = new BinaryWriter(fs);
                //保存文件头
                bw.Write(rgrp.h1);
                bw.Write(rgrp.in_scene);
                bw.Write(rgrp.bigmap_x);
                bw.Write(rgrp.bigmap_y);
                bw.Write(rgrp.scene_x);
                bw.Write(rgrp.scene_y);
                bw.Write(rgrp.unknow0);
                bw.Write(rgrp.scene_id);
                bw.Write(rgrp.unknow1);
                bw.Write(rgrp.nogninnur);
                bw.Write(rgrp.version);
                bw.Write(ItemTypeList.Count);
                for (int i = 0; i < ItemTypeList.Count; i++)
                    bw.Write(ItemTypeList[i]);
                bw.Write(ItemCountList.Count);
                for (int i = 0; i < ItemCountList.Count; i++)
                    bw.Write(ItemCountList[i]);
                //保存npc
                bw.Write(NPCList.Count);
                foreach (var n in NPCList)
                    n.Save(bw);
                //保存item
                bw.Write(ItemList.Count);
                foreach (var n in ItemList)
                    n.Save(bw);
                //保存scene
                bw.Write(SceneList.Count);
                foreach (var n in SceneList)
                    n.Save(bw);
                //保存skill
                bw.Write(SkillList.Count);
                foreach (var n in SkillList)
                    n.Save(bw);
                //保存shop
                bw.Write(ShopList.Count);
                foreach (var n in ShopList)
                    n.Save(bw);
                //保存队友
                for (int i = 0; i < Team.values.Length; i++)
                {
                    if (Team.values[i] < NPCList.Count)
                        bw.Write((int)Team.values[i]);
                    else
                        bw.Write((int)-1);
                }
                bw.Write(rgrp.md5);
                bw.Write(rgrp.week);
                bw.Write(rgrp.diffculty);
                bw.Write(rgrp.game_mode);
                bw.Write(rgrp.charmap);
                bw.Write(rgrp.game_time);
                bw.Write(rgrp.total_game_time);
                bw.Write(rgrp.save_time);
                bw.Write(rgrp.unknow_int);
                //保存文件尾
                fs.Write(rgrp.ender, 0, rgrp.ender.Length);
                fs.Close();
                //保存scene map
                fs = File.OpenWrite(path+"\\save\\s.grp");
                //count = (int)(fs.Seek(0, SeekOrigin.End) / 49152);
                for (int i = 0; i < SceneList.Count; i++)
                {
                    for (int level = 0; level < 6; level++)
                        for (int y = 0; y < 64; y++)
                            for (int x = 0; x < 64; x++)
                            {
                                ushort value = SceneList[i].map[level, y, x];
                                fs.WriteByte((byte)(value & 0xff));
                                fs.WriteByte((byte)(value >> 8));
                            }
                }
                fs.Close();
                //保存scene event
                fs = File.OpenWrite(path+"\\save\\d.grp");
                for (int i = 0; i < SceneList.Count; i++)
                    for (int j = 0; j < 200; j++)
                    {
                        JsSceneEvent e = SceneList[i].events[j];
                        for (int k = 0; k < e.values.Length; k++)
                        {
                            fs.WriteByte((byte)(e.values[k] & 0xff));
                            fs.WriteByte((byte)(e.values[k] >> 8));
                        }

                    }
                bw.Close();
                fs.Close();
                return null;
            }
            catch(Exception e)
            {
                return e.ToString();
            }
        }

        public string LoadTask(string path)
        {
            try
            {
                var fs = File.OpenRead(path + "\\save\\j.grp");
                var br = new BinaryReader(fs);



                br.Close();
                fs.Close();
                return null;
            }
            catch (Exception e)
            {
                return e.ToString();
            }
        }

         

        public void SetChoosePicMode(int idx)
        {
            SelectIndex = idx;
            Mode = GameMode.PicChoose;
            CellW = 64; CellH = 64;
            ResetCell();
        }

        public void SetSceneEventMode()
        {
            Mode = GameMode.SceneEventEdit;
            CurrentLevel = -1;
        }

        public void SetSceneMapMode()
        {
            Mode = GameMode.SceneEdit;
        }

        public void SetEditingLevel(int level)
        {
            CurrentLevel = level;
        }

        public System.Drawing.Bitmap GetPicBitmap(int idx)
        {
            if (idx >= 0 && idx < PicList.Count)
            {
                JsPic pic = PicList[idx];
                if (pic != null && pic.texture != null)
                {
                    var bmp = new System.Drawing.Bitmap(pic.texture.Width, pic.texture.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    //bmp.Tag = idx;
                    int[] data = new int[bmp.Width * bmp.Height];
                    pic.texture.GetData<int>(data);
                    for (int i = 0; i < data.Length; i++)
                    {
                        uint d = (uint)data[i];
                        d = ((d & 0xff) << 16) | (d & 0xff00ff00) | ((d & 0xff0000) >> 16);
                        data[i] = (int)d;
                    }
                    var bmp_data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat);
                    System.Runtime.InteropServices.Marshal.Copy(data, 0, bmp_data.Scan0, data.Length);
                    bmp.UnlockBits(bmp_data);
                    return bmp;
                }
            }
            return null;
        }

        public JsScene ChangeScene(int idx)
        {
            if (idx >= 0 && idx < SceneList.Count)
            {
                LastMapOffset = MapOffset;
                LastScene = CurrentScene;
                CurrentScene = SceneList[idx];
                MapOffset.X = -Width / 2;
                MapOffset.Y = 576 - Height / 2;
                return CurrentScene;
            }
            return null;
        }

        public void ChangeScene(JsScene scene)
        {
            if (scene != CurrentScene)
            {
                LastMapOffset = MapOffset;
                LastScene = CurrentScene;
                CurrentScene = scene;
                MapOffset.X = -Width / 2;
                MapOffset.Y = 576 - Height / 2;
            }
        }

        public JsScene ChangeLastScene()
        {
            CurrentScene = LastScene;
            MapOffset = LastMapOffset;
            return CurrentScene;
        }

        public void ResetCell()
        {
            CellX = Width / CellW;
            CellY = (PicList.Count - 1) / CellX + 1;
            CellOffsetY = SelectIndex / CellX * CellH;
            CellScrollY(0);
        }

        public void SetLevelVisible(int level, bool visible)
        {
            LevelVisible[level] = visible;
        }

        public void SelectScenePos(int x, int y)
        {
            x &= 63;
            y &= 63;
            SelectX = x;
            SelectY = y;
            MapOffset.X = (x - y) * 18 - Width / 2;
            MapOffset.Y = (x + y) * 9 - Height / 2;
        }

        public void CellScrollY(int dy)
        {
            CellOffsetY -= dy;
            if (CellOffsetY < 0) CellOffsetY = 0;
            int max = CellY * CellH - Height;
            if (CellOffsetY > max)
                CellOffsetY = max;
        }

        public bool PickCell(int x, int y, out int xx, out int yy)
        {
            x += (int)MapOffset.X;
            y += (int)MapOffset.Y + 18;
            xx = ((y * 2 + x) / 36);
            yy = ((y * 2 - x) / 36);
            return (xx >= 0 && xx < 64 && yy >= 0 && yy < 64);
        }

        public int PickPic(int x, int y)
        {
            int xx = x / CellW;
            if (xx >= 0 && xx < CellX)
            {
                int idx = (y + CellOffsetY) / CellH * CellX + xx;
                if (idx >= 0 && idx < PicList.Count)
                {
                    return idx;
                }
            }
            return -1;
        }

        public void SetCurPaintPic(int idx, int offset = 0)
        {
            CurPaintPicIdx = idx;
            CurPaintPicOffset = offset;
        }

        public void SetCurPaintOffset(int offset)
        {
            CurPaintPicOffset = offset;
        }

        public void PaintMap(int x, int y)
        {
            if (CurrentScene != null && CurrentLevel >= 0 && CurrentLevel < 3)
            {
                x += (int)MapOffset.X;
                y += (int)MapOffset.Y + 18;
                int xx = ((y * 2 + x) / 36);
                int yy = ((y * 2 - x) / 36);
                CurrentScene.SetMap(CurrentLevel, xx, yy, (ushort)(CurPaintPicIdx * 2));
                if (CurrentLevel > 0)
                {
                    CurrentScene.SetMap(CurrentLevel + 3, xx, yy, (ushort)CurPaintPicOffset);
                }
            }
        }

        public string ConverToString(JsEventLine e)
        {
            StringBuilder sb = new StringBuilder();
            if (e.values != null)
            {
                for (int i = 0; i < e.values.Length; i++)
                {
                    if(i!=0) sb.Append(", ");
                    ushort v = e.values[i];
                    JsVar t=null;
                    if (e.type.types != null && i < e.type.types.Length)
                        t = e.type.types[i];
;                   if(t==null)
                    {
                        sb.Append(e.values[i].ToString());
                    }
                    else if (t.type == JsVarType.js_item)
                    {
                        if (v < ItemList.Count)
                        {
                            sb.Append(ItemList[v].Name);
                            continue;
                        }
                    }
                    else if (t.type == JsVarType.js_npc)
                    {
                        if (v < NPCList.Count)
                        {
                            sb.Append(NPCList[v].Name);
                            continue;
                        }
                    }
                    else if (t.type == JsVarType.js_scene)
                    {
                        if (v < SceneList.Count)
                        {
                            sb.Append(SceneList[v].Name);
                            continue;
                        }
                    }
                    else if (t.type == JsVarType.js_skill)
                    {
                        if (v < SkillList.Count)
                        {
                            sb.Append(SkillList[v].Name);
                            continue;
                        }
                    }
                    else if (t.type == JsVarType.js_shop)
                    {
                        if (v < ShopList.Count)
                        {
                            sb.Append(ShopList[v].ToString());
                            continue;
                        }
                    }
                    else if (t.type == JsVarType.js_suit)
                    {
                        if (v < SuitList.Count)
                        {
                            sb.Append(SuitList[v].ToString());
                            continue;
                        }
                    }
                    else if (t.type == JsVarType.js_pos)
                    {
                        sb.Append(e.GetPos(i, t.min).ToString());
                        continue;
                    }
                    else if (t.type == JsVarType.str)
                    {
                        sb.Append(e.GetString(i, t.max));
                        continue;
                    }
                    else if (t.type == JsVarType.js_talk || t.type == JsVarType.js_task)
                    {
                        if (v < TalkList.Count)
                        {
                            sb.Append(TalkList[v]);
                            continue;
                        }
                    }
                    else if(t.type==JsVarType.int16)
                    {
                        sb.Append(((short)e.values[i]).ToString());
                        continue;
                    }
                    else if (t.type == JsVarType.hidden)
                    {
                        continue;
                    }
                    sb.Append(e.values[i].ToString());
                }
            }
            return sb.ToString();
        }


        public Object GetObj(JsVar var_type, ushort idx)
        {
            if(var_type.fields!=null)
            {
                foreach(var o in var_type.fields)
                    if(o.value==idx)
                        return o;
            }
            if (idx >= 0)
            {
                if (var_type.type == JsVarType.js_item)
                {
                    if (idx < ItemList.Count)
                        return ItemList[idx];
                }
                else if (var_type.type == JsVarType.js_npc)
                {
                    if (idx < NPCList.Count)
                        return NPCList[idx];
                }
                else if (var_type.type == JsVarType.js_event)
                {
                    if (idx < EventList.Count)
                        return EventList[idx];
                }
                else if (var_type.type == JsVarType.js_scene)
                {
                    if (idx < SceneList.Count)
                        return SceneList[idx];
                }
                else if (var_type.type == JsVarType.js_skill)
                {
                    if (idx < SkillList.Count)
                        return SkillList[idx];
                }
                else if (var_type.type == JsVarType.js_shop)
                {
                    if (idx < ShopList.Count)
                        return ShopList[idx];
                }
                else if (var_type.type == JsVarType.js_talk)
                {
                    if (idx < TalkList.Count)
                        return TalkList[idx];
                }
                else if (var_type.type == JsVarType.js_task)
                {
                    if (idx < TalkList.Count)
                    {
                       return new JsListItem(TalkList[idx], idx);
                    }
                }
            }
            return null;
        }

        public Object[] GetObjList(JsVarType type)
        {
            if (type == JsVarType.js_item)
            {
                 return ItemList.ToArray();
            }
            else if (type == JsVarType.js_npc)
            {
                return NPCList.ToArray();
            }
            else if (type == JsVarType.js_event)
            {
                return EventList.ToArray();
            }
            else if (type == JsVarType.js_scene)
            {
                return SceneList.ToArray();
            }
            else if (type == JsVarType.js_skill)
            {
                return SkillList.ToArray();
            }
            else if (type == JsVarType.js_shop)
            {
                return ShopList.ToArray();
            }
            else if (type == JsVarType.js_task)
            {
                JsListItem[] list = new JsListItem[TaskList.Count];
                for (int i = 0; i < TaskList.Count; i++)
                    list[i] = new JsListItem(TalkList[TaskList[i]], TaskList[i]);
                    return list;
            }
            return null;
        }

        public int AddTalk(string msg)
        {
            if (TalkList.Count >= 0xfffe)
                return 0;
            TalkList.Add(msg);
            return TalkList.Count - 1;
        }

        public string GetTalk(int idx)
        {
            if (idx < TalkList.Count)
                return TalkList[idx];
            return null;
        }

        public void SetTalk(ushort idx,string msg)
        {
            if (idx < TalkList.Count)
                TalkList[idx] = msg;
        }

        public void RemoveTalkInEventLine(JsEventLine line)
        {
            if(line.type.cmd==1)  //对话语句
            {
                if (line.values[0] > 0)
                    RemoveTalk(line.values[0]);
            }
        }

        public void RemoveTalkInSkill(JsSkill skill)
        {
            if (skill.values[9] > 0)
                RemoveTalk(skill.values[9]);
            if (skill.values[11] > 0)
                RemoveTalk(skill.values[11]);
            if (skill.values[12] > 0)
                RemoveTalk(skill.values[12]);
        }

        public string FindTaskRef(ushort idx)
        {
            foreach (var e in EventList)
            {
                foreach (var el in e.Lines)
                {
                    if (el.type.types != null)
                        for (int i = 0; i < el.values.Length; i++)
                            if (el.type.types[i].type == JsVarType.js_task)
                                if (el.values[i] == idx)
                                    return "事件(" + e.ToString() + ")的语句：" + el.ToString();
                }
            }
            return null;
        }

        public void RemoveTask(ushort idx)
        {
            if(TaskList.Contains(idx))
            {
                TaskList.Remove(idx);
                RemoveTalk(idx);
            }
        }

        public void RemoveTalk(ushort idx)
        {
            if(idx<TalkList.Count)
            {
                TalkList.RemoveAt(idx);
                //ModifyObjectRef(JsVarType.js_talk,idx);
                foreach(var e in EventList)
                {
                    foreach(var el in e.Lines)
                    {
                        if (el.type.types != null)
                            for (int i = 0; i < el.values.Length; i++)
                                if (i < el.type.types.Length && el.type.types[i].type == JsVarType.js_talk)
                                    if (el.values[i] > idx)
                                        el.values[i]--;
                    }
                }
                foreach(var s in SkillList)
                {
                   for(int i=0;i<s.values.Length;i++)
                        if (i<JsSkill.types.Length&&JsSkill.types[i].type == JsVarType.js_talk)
                            if (s.values[i] > idx)
                                s.values[i]--;
                }
                for (int i = 0; i < TaskList.Count; i++)
                    if (TaskList[i] > idx)
                        TaskList[i]--;
            }
        }


        public string FindObjectRef(JsVarType t, int idx)
        {
            foreach(var n in SceneList)
            {
                if (n.IsObjectRef(JsScene.types, t, (ushort)idx))
                    return "场景：" + n.ToString();
            }
            foreach(var n in NPCList)
            {
                if (n.IsObjectRef(JsNPC.types, t, (ushort)idx))
                    return "人物：" + n.ToString();
            }
            foreach (var n in ItemList)
            {
                if (n.IsObjectRef(JsItem.types, t, (ushort)idx))
                    return "物品：" + n.ToString();
            }
            foreach (var n in SkillList)
            {
                if (n.IsObjectRef(JsSkill.types, t, (ushort)idx))
                    return "武功：" + n.ToString();
            }
            foreach (var n in ShopList)
            {
                if (n.IsObjectRef(JsShop.types, t, (ushort)idx))
                    return "商店：" + n.ToString();
            }
            foreach (var n in SuitList)
            {
                if (n.IsObjectRef(JsSuit.types, t, (ushort)idx))
                    return "套装：" + n.ToString();
            }
            if(t==JsVarType.js_item&&ItemTypeList.Contains(idx))
            {
                return "拥有的道具";
            }
            if (t == JsVarType.js_npc && TeamNPCList.Contains((ushort)idx))
            {
                return "可加入的人员列表";
            }

            foreach (var n in EventList)
            if (n.idx != idx)
            {
                foreach (var e in n.Lines)
                {
                    JsEventType type;
                    if(e.type.cmd==50 && ( type = JsEventType.GetEvent50Type(e.values[0]))!=null)  //如果是合法的50指令
                    {
                        if (e.IsObjectRef(type.types, t, (ushort)idx))
                            return "事件(" + n.ToString() + ")的语句：" + e.ToString();
                    }
                    else if (e.IsObjectRef(e.type.types, t, (ushort)idx))
                            return "事件(" + n.ToString() + ")的语句：" + e.ToString();
                        
                }
            }
            return null;
        }

        public void ModifyObjectRef(JsVarType t, int idx)
        {
            foreach (var n in SceneList)
            {
                n.ModifyObjectRef(JsScene.types, t, (ushort)idx);
            }
            foreach (var n in NPCList)
            {
                n.ModifyObjectRef(JsNPC.types, t, (ushort)idx);
            }
            foreach (var n in ItemList)
            {
                n.ModifyObjectRef(JsItem.types, t, (ushort)idx);
            }
            foreach (var n in SkillList)
            {
                n.ModifyObjectRef(JsSkill.types, t, (ushort)idx);
            }
            foreach (var n in ShopList)
            {
                n.ModifyObjectRef(JsShop.types, t, (ushort)idx);
            }
            foreach (var n in SuitList)
            {
                n.ModifyObjectRef(JsSuit.types, t, (ushort)idx);
            }
            if (t == JsVarType.js_item)
            {
                for (int i = 0; i < ItemTypeList.Count; i++)
                    if (ItemTypeList[i] > idx)
                        ItemTypeList[i]--;
            }
            if (t == JsVarType.js_npc)
            {
                for (int i = 0; i < TeamNPCList.Count; i++)
                    if (TeamNPCList[i] > idx)
                        TeamNPCList[i]--;
            }
            foreach (var n in EventList)
                foreach (var e in n.Lines)
                {
                    e.ModifyObjectRef(e.type.types, t, (ushort)idx);
                }
        }


        public Object AddObject(JsVarType type,JsObj clone_obj=null)
        {
            if(type==JsVarType.js_event)
            {
                JsEvent e = new JsEvent();
                e.AddLine(JsEventType.GetEventType(0), 0);
                e.AddLine(JsEventType.GetEventType(0xffff), 1);
                e.idx = EventList.Count;
                EventList.Add(e);
                return e;
            }
            else if(type==JsVarType.js_npc)
            {
                JsNPC e = new JsNPC();
                e.idx = NPCList.Count;
                NPCList.Add(e);
                if (clone_obj != null) e.CloneFrom(clone_obj);
                return e;
            }
            else if (type == JsVarType.js_item)
            {
                JsItem e = new JsItem();
                e.idx = ItemList.Count;
                ItemList.Add(e);
                if (clone_obj != null) e.CloneFrom(clone_obj);
                return e;
            }
            else if (type == JsVarType.js_skill)
            {
                JsSkill e = new JsSkill();
                e.idx = SkillList.Count;
                SkillList.Add(e);
                if (clone_obj != null) e.CloneFrom(clone_obj);
                e.values[9] = 0;
                e.values[11] = 0;
                e.values[12] = 0;
                return e;
            }
            else if (type == JsVarType.js_scene)
            {
                JsScene e = new JsScene();
                e.idx = SceneList.Count;
                SceneList.Add(e);
                if (clone_obj != null) e.CloneFrom(clone_obj);
                return e;
            }
            else if (type == JsVarType.js_shop)
            {
                JsShop e = new JsShop();
                e.idx = ShopList.Count;
                ShopList.Add(e);
                if (clone_obj != null) e.CloneFrom(clone_obj);
                return e;
            }
            else if (type == JsVarType.js_suit)
            {
                JsSuit e = new JsSuit();
                e.idx = SuitList.Count;
                SuitList.Add(e);
                if (clone_obj != null) e.CloneFrom(clone_obj);
                return e;
            }
            return null;
        }


    }  //class



}
